const cookie = require("cookie");
const setCookieParser = require("set-cookie-parser");
const jsdom = require("jsdom");
const util = require("util");
const qs = require("querystring");
const url = require("url");
const randomstring = require("randomstring");
const innertext = require("innertext");
const axios = require("axios").default.create({
  headers: {
    "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:57.0) Gecko/20100101 Firefox/57.0"
  },
  timeout: 1000 * 10,
  maxRedirects: 0,
  maxContentLength: Number.MAX_SAFE_INTEGER
});

class GiteeWeb {
  /**
   * 
   * @param {String} user_login 手机/邮箱/个性域名
   * @param {String} user_password 
   */
  constructor(user_login, user_password) {
    this.user_login = user_login;
    this.user_password = user_password;
    this.cookies = [{
      name: "",
      value: ""
    }];
    this.loginned = this.login();
  }

  get cookie_request_header() {
    return this.cookies.filter(c => c.name && c.value).map(c => cookie.serialize(c.name, c.value, {
      encode: val => val
    })).join("; ")
  }

  /**
   * 
   * @param {String} set_cookie 
   * @api private
   */
  __dealWithResponseSetcookieHeaders(set_cookie) {
    if (util.isArray(set_cookie)) {
      for (let sc of set_cookie) {
        this.__dealWithResponseSetcookieHeaders(sc);
      }
      return;
    }
    if (util.isString(set_cookie) && set_cookie) {
      let parsed = setCookieParser(set_cookie);
      parsed.forEach(psd_set => {
        let i = this.cookies.findIndex(c => c.name == psd_set.name);
        if (i >= 0) {
          this.cookies[i].value = psd_set.value;
        } else {
          this.cookies.push({
            name: psd_set.name,
            value: psd_set.value
          })
        }
      });
    }
  }

  /**
   * @returns {Promise<{ok:Boolean,msg:String}>}
   */
  login() {
    return new Promise(resolve => {
      //https://gitee.com/login
      axios.get("https://gitee.com/login", {
        validateStatus: s => s == 200
      }).then(axresp => {
        this.__dealWithResponseSetcookieHeaders(axresp.headers['set-cookie']);
        let document = (new jsdom.JSDOM(axresp.data)).window.document;
        let form = document.querySelector("form#new_user");
        if (!form) {
          return resolve({
            ok: false,
            msg: "no [form#new_user] element"
          })
        }
        let i_utf8 = form.querySelector("input[name='utf8']");
        let i_token = form.querySelector("input[name='authenticity_token']");
        if (!(i_token && i_utf8)) {
          return resolve({
            ok: false,
            msg: "no input[name='utf8'] or input[name='authenticity_token'] element found"
          })
        }
        axios.post("https://gitee.com/login", qs.stringify({
          utf8: i_utf8.getAttribute("value"),
          authenticity_token: i_token.getAttribute("value"),
          captcha: "",
          'user[login]': this.user_login,
          "user[password]": this.user_password,
          "user[remember_me]": 1,
          commit: "登 录"
        }), {
          headers: {
            cookie: this.cookie_request_header,
            referer: "https://gitee.com/login",
          },
          validateStatus: s => s >= 300 && s <= 399
        }).then(axresp => {
          this.__dealWithResponseSetcookieHeaders(axresp.headers['set-cookie']);
          let location = axresp.headers['location'];
          if (location.endsWith("/events")) {
            resolve({
              ok: true,
              msg: "true"
            });
          } else {
            return resolve({
              ok: false,
              msg: `header 'location' is ${location} `
            })
          }
        }).catch(axerr => {
          if (axerr.response) {
            resolve({
              ok: false,
              msg: `HTTP ${axerr.response.status} ${axerr.response.statusText} : ${axerr.response.data}`
            })
          } else {
            resolve({
              ok: false,
              msg: axerr.message ? axerr.message : util.inspect(axerr)
            })
          }
        })

      }).catch(axerr => {
        if (axerr.response) {
          resolve({
            ok: false,
            msg: `HTTP ${axerr.response.status} ${axerr.response.statusText} : ${axerr.response.data}`
          })
        } else {
          resolve({
            ok: false,
            msg: axerr.message ? axerr.message : util.inspect(axerr)
          })
        }
      })
    })
  }

  get OnRepo() {
    let gitee_web = this;
    return class GitWebOnRepo {
      /**
       * 
       * @param {String} owner 
       * @param {String} repo 
       */
      constructor(owner, repo) {
        this.owner = owner;
        this.repo = repo;
      }

      /**
       * 
       * @param {String} name 
       * @param {String} color 
       * @returns {Promise<{ok:Boolean,msg:String,label_id:Number}>}
       */
      createLabel(name, color = "FF0080") {
        return new Promise(async resolve => {
          let o_getCsrf = await this.__getCsrfToken(`https://gitee.com/${this.owner}/${this.repo}/issues`);
          if (!o_getCsrf.ok) {
            return resolve({
              ok: false,
              msg: `error when __getCsrfToken():${o_getCsrf.msg}`,
              label_id: 0
            })
          }
          axios.post(`https://gitee.com/${this.owner}/${this.repo}/labels`, qs.stringify({
            'label[name]': name,
            'label[color]': color
          }), {
            headers: {
              cookie: gitee_web.cookie_request_header,
              'X-CSRF-Token': o_getCsrf.CSRF_TOKEN,
              "X-Requested-With": "XMLHttpRequest",
              /**@description  其有无会影响正常的创建是200还是302*/
              "Origin": "https://gitee.com",
              "Referer": `https://gitee.com/${this.owner}/${this.repo}/issues`
            },
            validateStatus: s => s == 200 || s == 302
          }).then(axresp => {
            // debugger
            //referer,origin 可以不要
            //length=21 失败
            //length=20 时ok
            //`\\\\34567891113151719+` 成功了
            //`\\34567891113151719+` 成功了
            //"https://nyaa.si/12578" 失败了
            //"https:/nyaa.si/12578" 成功了
            //可见是不允许连续两个/
            //正常时 message="ok" status=0 id=Number
            //不正常 message="failed" status=1
            if (axresp.status == 200) {
              if (axresp.data['status'] == 0) {
                return resolve({
                  ok: true,
                  msg: "ok",
                  label_id: axresp.data['id']
                })
              } else {
                return resolve({
                  ok: false,
                  msg: `create label ${name} failed!pls check if the label is too long or contains '//' `
                })
              }
            } else {
              debugger
            }
            //302 "https://gitee.com/patricia_of_end/webtest/issues" 是因为冲突了?
          }).catch(axerr => {

            //403 当没有CSRF_TOKEN时出现
            if (axerr.response) {
              return resolve({
                ok: false,
                msg: `HTTP ${axerr.response.status + axerr.response.statusText};${util.inspect(axerr.response.data)}`
              })
            } else {
              return resolve({
                ok: false,
                msg: axerr.message ? axerr.message : util.inspect(axerr)
              })
            }
          })
        })
      }

      /**
       * 
       * @param {String} gitee_weblink 
       * @returns {Promise<{ok:Boolean,msg:String,CSRF_TOKEN:String}>}
       */
      __getCsrfToken(gitee_weblink) {
        return new Promise(resolve => {
          axios.get(gitee_weblink, {
            headers: {
              cookie: gitee_web.cookie_request_header
            },
            validateStatus: s => s == 200
          }).then(axresp => {
            let document = (new jsdom.JSDOM(axresp.data)).window.document;
            let meta_csrf = document.querySelector("meta[name='csrf-token']");
            if (!meta_csrf) {
              return resolve({
                ok: false,
                msg: `no META(name=csrf-token) element found`
              })
            }
            gitee_web.__dealWithResponseSetcookieHeaders(axresp.headers['set-cookie']);
            resolve({
              ok: true,
              msg: "ok",
              CSRF_TOKEN: meta_csrf.getAttribute("content")
            })
          }).catch(axerr => {
            if (axerr.response) {
              return resolve({
                ok: false,
                msg: `HTTP ${axerr.response.status + axerr.response.statusText};${util.inspect(axerr.response.data)}`
              })
            } else {
              return resolve({
                ok: false,
                msg: axerr.message ? axerr.message : util.inspect(axerr)
              })
            }
          })
        })
      }
    }
  }
}

if (!module.parent) {
  let gitee = new GiteeWeb("patricia_of_end", "os65huji");
  gitee.loginned.then(o => {
    let on_repo = new gitee.OnRepo("patricia_of_end", "webtest");
    setInterval($ => {
      on_repo.createLabel(randomstring.generate(5), "f08899")
    },1000)

  })
}

module.exports = {
  GiteeWeb
}